package cn.sciento.starter.social.qq.api;

import cn.sciento.core.convertor.ApplicationContextHelper;
import com.fasterxml.jackson.databind.ObjectMapper;
import cn.sciento.starter.social.core.common.api.AbstractSocialApi;
import cn.sciento.starter.social.core.configuration.SocialProperties;
import cn.sciento.starter.social.core.exception.CommonSocialException;
import cn.sciento.starter.social.core.exception.ProviderUserNotFoundException;
import cn.sciento.starter.social.core.provider.Provider;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DefaultQQApi extends AbstractSocialApi implements QQApi {
  private static final Logger LOGGER = LoggerFactory.getLogger(DefaultQQApi.class);
  
  private String userInfoUrl;
  
  private String openIdUrl;
  
  private String appId;
  
  private String openId;
  
  private String unionId;
  
  private static final ObjectMapper mapper = new ObjectMapper();
  
  public DefaultQQApi(String accessToken, Provider provider) {
    super(accessToken);
    this.appId = provider.getAppId();
    this.userInfoUrl = provider.getUserInfoUrl() + "?oauth_consumer_key={appId}&openid={openId}";
    this.openIdUrl = provider.getOpenIdUrl();
    if (isGetUnionId())
      this.openIdUrl += "?unionid=1"; 
  }
  
  public synchronized QQUser getUser() {
    if (!isAuthorized())
      throw new CommonSocialException("hoth.social.userNotAuthorized"); 
    if (StringUtils.isBlank(this.openId)) {
      QQMe me = getMe();
      this.openId = me.getOpenId();
      this.unionId = me.getUnionId();
    } 
    String result = (String)getRestTemplate().getForObject(this.userInfoUrl, String.class, new Object[] { this.appId, this.openId });
    QQUser user = null;
    try {
      user = (QQUser)mapper.readValue(result, QQUser.class);
    } catch (Exception e) {
      LOGGER.error("parse qq UserInfo error. result : {}", result);
    } 
    if (user == null || StringUtils.isBlank(user.getNickname())) {
      LOGGER.info("not found provider user, result user={}", user);
      throw new ProviderUserNotFoundException("hoth.social.providerUserNotFound");
    } 
    user.setOpenId(this.openId);
    user.setUnionId(this.unionId);
    return user;
  }
  
  private QQMe getMe() {
    String openIdResult = (String)getRestTemplate().getForObject(this.openIdUrl, String.class);
    if (StringUtils.isBlank(openIdResult) || openIdResult.contains("error")) {
      LOGGER.warn("request social user's openId return error, result={}", openIdResult);
      throw new CommonSocialException("hoth.social.openIdNotFound");
    } 
    String[] arr = StringUtils.substringBetween(openIdResult, "{", "}").replace("\"", "").split(",");
    String openid = null;
    String unionid = null;
    for (String s : arr) {
      if (s.contains("openid")) {
        openid = s.split(":")[1];
      } else if (s.contains("unionid")) {
        unionid = s.split(":")[1];
      } 
    } 
    return new QQMe(openid, unionid);
  }
  
  private boolean isGetUnionId() {
    SocialProperties socialProperties =  ApplicationContextHelper.getContext().getBean(SocialProperties.class);
    return socialProperties.getQq().isGetUnionId();
  }
  
  private static class QQMe {
    private String openId;
    
    private String unionId;
    
    public QQMe(String openId, String unionId) {
      this.openId = openId;
      this.unionId = unionId;
    }
    
    public String getOpenId() {
      return this.openId;
    }
    
    public String getUnionId() {
      return this.unionId;
    }
  }
}
